package com.kedacom.ctsp.authority.controller;

import com.google.common.collect.Lists;
import com.kedacom.ctsp.authority.entity.Resource;
import com.kedacom.ctsp.authority.entity.User;
import com.kedacom.ctsp.authority.service.ResourceService;
import com.kedacom.ctsp.authority.service.UserService;
import com.kedacom.ctsp.authority.vo.ResourceVO;
import com.kedacom.ctsp.authz.AuthenticationService;
import com.kedacom.ctsp.authz.entity.AuthResource;
import com.kedacom.ctsp.authz.entity.Authentication;
import com.kedacom.ctsp.authz.entity.UserBean;
import com.kedacom.ctsp.authz.exception.UnauthorizedException;
import com.kedacom.ctsp.authz.utils.UserBeanUtil;
import com.kedacom.ctsp.lang.StringUtil;
import com.kedacom.ctsp.logging.AccessLogger;
import com.kedacom.ctsp.orm.param.TermEnum;
import com.kedacom.ctsp.web.controller.message.ResponseMessage;
import com.kedacom.ctsp.web.controller.util.QueryParamUtil;
import com.kedacom.ctsp.web.entity.TreeSupportBean;
import com.kedacom.ctsp.web.entity.page.PagerResult;
import com.kedacom.ctsp.web.entity.param.QueryParamEntity;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.kedacom.ctsp.web.controller.message.ResponseMessage.ok;

@RequestMapping("authy")
@AccessLogger("提供authority基本方法")
@Api(tags = "rbac-authz", description = "提供基本的授权功能")
@ResponseBody
@Slf4j
public class AuthorityController {
    @Autowired
    private ResourceService resourceService;
    @Autowired
    protected AuthenticationService authenticationService;
    @Autowired
    private UserService userService;

    /**
     * 前登录用户拥有的资源(树形列表)
     * 不支持分页
     *
     * @param param
     * @return
     */
    @GetMapping(path = "/resource/tree/me")
    @AccessLogger("{query_as_tree}")
    @ApiOperation("按条件获取当前登录用户拥有的树形资源")
    @ApiResponses({
            @ApiResponse(code = 200, message = "查询成功"),
            @ApiResponse(code = 401, message = "未授权"),
            @ApiResponse(code = 403, message = "无权限"),
            @ApiResponse(code = 404, message = "数据不存在")
    })
    public ResponseMessage<List<ResourceVO>> listMyAsTree(QueryParamEntity param, HttpServletRequest request) {

        Set<String> resourceIds = currentResourceIds();
        if (CollectionUtils.isNotEmpty(resourceIds)) {
            QueryParamUtil.paddingTerms(param, request);
            param.and(Resource.ID, TermEnum.in, resourceIds);
            List<Resource> resources = resourceService.selectAsTree(param);
            List<ResourceVO> resourceVOList = resources.stream().map(r -> {
                ResourceVO resourceVO = resourceService.createInstance(ResourceVO.class);
                resourceVO.convertFrom(r);
                return resourceVO;
            }).collect(Collectors.toList());

            ResponseMessage<List<ResourceVO>> result = ok(resourceVOList);
            result.exclude(TreeSupportBean.class, TreeSupportBean.PARENT);
            return result;
        } else {
            return ok(Lists.newArrayList());
        }
    }

    @GetMapping(path = "/child/{id}/me")
    @AccessLogger("{query_children}")
    @ApiOperation("按父id获取子节点")
    @ApiResponses({
            @ApiResponse(code = 200, message = "查询成功"),
            @ApiResponse(code = 401, message = "未授权"),
            @ApiResponse(code = 403, message = "无权限"),
            @ApiResponse(code = 404, message = "数据不存在")
    })
    public ResponseMessage<PagerResult<ResourceVO>> listMyAllChildren(@PathVariable String id, QueryParamEntity param, HttpServletRequest request) {
        Set<String> resourceIds = currentResourceIds();

        QueryParamUtil.paddingTerms(param, request);
        param.and(Resource.ID, TermEnum.in, resourceIds);

        PagerResult<Resource> pagerResult = resourceService.selectAllChildNodePager(id, param);

        ResponseMessage<PagerResult<ResourceVO>> result = ok(pagerResult.convertTo(
                r -> {
                    ResourceVO resourceVO = resourceService.createInstance(ResourceVO.class);
                    resourceVO.convertFrom(r);
                    return resourceVO;
                }
        ));
        return result;
    }

    /**
     * 当前登录用户拥有的资源ids
     *
     * @return
     */
    private Set<String> currentResourceIds() {
        Authentication authentication = Authentication.current().orElseThrow(UnauthorizedException::new);
        //通过接口获取，获取资源
        Set<AuthResource> myResources = authenticationService.getAuthResource(authentication);
        Set<String> resourceIds = myResources.stream().map(AuthResource::getId).collect(Collectors.toSet());
        return resourceIds;
    }

    @PostMapping("/checkLogin")
    @AccessLogger("检查登录信息是否正确")
    @ApiOperation("检查登录信息是否正确")
    public ResponseMessage<String> checkLogin(HttpServletRequest request) {
        UserBean authUser = UserBeanUtil.createLoginUserBean(request);
        //用户名为空
        if (StringUtils.isBlank(authUser.getUsername())) {
            String errorMsg = StringUtil.format("auth.authz.username_isnull");
            return ResponseMessage.error(HttpStatus.FORBIDDEN.value(), errorMsg);
        }
        User user = userService.selectByUsername(authUser.getUsername());
        // 用户不存在
        if (user == null) {
            String errorMsg = StringUtil.format("auth.authz.username_notexists");
            return ResponseMessage.error(HttpStatus.FORBIDDEN.value(), errorMsg);
        }
//        BCryptPasswordEncoder bcp = new BCryptPasswordEncoder();
//        if (!bcp.matches(authUser.getPassword(), user.getPassword())) {
//            String errorMsg = StringUtil.format("auth.authz.username_password_error");
//            return ResponseMessage.error(HttpStatus.FORBIDDEN.value(), errorMsg);
//        }
        return ok();
    }
}
